Packages

Introduction

Build Website Website Website Website

Sliding windows

import sys
sys.path.insert(1, 'libs/')

import dynfc as dyn
import numpy as np
from numpy.random import seed, rand
import scipy as sc
from scipy import io
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.cm as cm
import matplotlib.patches as patches

font = {'weight' : 'regular',
        'size'   : 24}
plt.rc('font', **font)

ts = sc.io.loadmat('data/ts.mat')['ts']
ts = ts.transpose()

corr_mats, idx = dyn.corr_slide(ts,300,50)

idx.shape
> (24,)
a = [1,1,1,1,1.6]

fig,ax = plt.subplots(1)
fig.set_figheight(10)
fig.set_figwidth(20)
plt.style.use('tableau-colorblind10')
for i in range(5):
    
    plt.plot(2*i*a[i] + ts[i,]/1.4)   
    
> [<matplotlib.lines.Line2D object at 0x7fc2f0e74400>]
> [<matplotlib.lines.Line2D object at 0x7fc2f0e83a90>]
> [<matplotlib.lines.Line2D object at 0x7fc2f0e9c860>]
> [<matplotlib.lines.Line2D object at 0x7fc2f0e9c198>]
> [<matplotlib.lines.Line2D object at 0x7fc2f0e83c88>]
plt.xlabel('Time [TRs]')
> Text(0.5, 0, 'Time [TRs]')
plt.ylabel('BOLD')
> Text(0, 0.5, 'BOLD')
ax.tick_params(left=False)
ax.set_yticklabels([])
> [Text(0, -2.0, ''), Text(0, 0.0, ''), Text(0, 2.0, ''), Text(0, 4.0, ''), Text(0, 6.0, ''), Text(0, 8.0, ''), Text(0, 10.0, ''), Text(0, 12.0, ''), Text(0, 14.0, '')]
ax.set_ylim(-3,15.4)
> (-3.0, 15.4)
ax.set_xlim(0,1200)
> (0.0, 1200.0)
rect = patches.Rectangle((idx[0],-2.8),300,18,linewidth=4,edgecolor='#595959',facecolor='none')
ax.add_patch(rect)
> <matplotlib.patches.Rectangle object at 0x7fc2b7cc4e80>
rect = patches.Rectangle((idx[5],-2.8),300,18,linewidth=4,edgecolor='#A56B6B',facecolor='none')
ax.add_patch(rect)
> <matplotlib.patches.Rectangle object at 0x7fc2b7cd5240>
rect = patches.Rectangle((idx[9],-2.8),300,18,linewidth=4,edgecolor='#CE3E3E',facecolor='none')
ax.add_patch(rect)
> <matplotlib.patches.Rectangle object at 0x7fc2b7cd5550>
rect = patches.Rectangle((idx[16],-2.8),300,18,linewidth=4,edgecolor='#FF0000',facecolor='none')
ax.add_patch(rect)
> <matplotlib.patches.Rectangle object at 0x7fc2b7cd5860>
plt.show()

import sys
sys.path.insert(1, 'libs/')

import dynfc as dyn
import numpy as np
from numpy.random import seed, rand
import scipy as sc
from scipy import io
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.cm as cm
import matplotlib.patches as patches

aa = plt.figure(figsize = [6,6])
ax = sns.heatmap(corr_mats[:,:,0], 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = True, 
                 cbar = False)
ax.axis('off')
> (0.0, 200.0, 200.0, 0.0)
ax.tick_params(left=False, bottom=False)
    
plt.show()

aa = plt.figure(figsize = [6,6])
ax = sns.heatmap(corr_mats[:,:,5], 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = True, 
                 cbar = False)
ax.axis('off')
> (0.0, 200.0, 200.0, 0.0)
ax.tick_params(left=False, bottom=False)
    
plt.show()

aa = plt.figure(figsize = [6,6])
ax = sns.heatmap(corr_mats[:,:,9], 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = True, 
                 cbar = False)
ax.axis('off')
> (0.0, 200.0, 200.0, 0.0)
ax.tick_params(left=False, bottom=False)
    
plt.show()

aa = plt.figure(figsize = [6,6])
ax = sns.heatmap(corr_mats[:,:,16], 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = True, 
                 cbar = False)
ax.axis('off')
> (0.0, 200.0, 200.0, 0.0)
ax.tick_params(left=False, bottom=False)
    
plt.show()

Cofluctuations

import sys
sys.path.insert(1, 'libs/')

import numpy as np
import scipy as sc
from scipy import io
import dynfc as dyn
import seaborn as sns
import matplotlib.pyplot as plt

ts = sc.io.loadmat('data/ts.mat')['ts']
ts = ts.transpose()

mat1, rss = dyn.corr_slide(ts,24)
mat1 = mat1[:,:,0]

aa = plt.figure(figsize = [6,6])
ax = sns.heatmap(mat1, 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = False, 
                 cbar = True)
ax.axis('off')
> (0.0, 200.0, 200.0, 0.0)
ax.tick_params(left=False, bottom=False)
plt.show()

upt = np.triu_indices(mat1.shape[0], k = 1)
vec = (mat1[upt])

toPlot = np.zeros((vec.shape[0],1))
toPlot[:,0] = vec

aa = plt.figure(figsize = (12/50,4))
ax = sns.heatmap(toPlot[:,0:1], 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = False, 
                 cbar = False)
ax.axis('off')
> (0.0, 1.0, 19900.0, 0.0)
plt.show()

edges_series, corr_mats, rss = dyn.cofluct(ts, 24)

aa = plt.figure(figsize = (12,4))
> /Users/runner/Library/r-miniconda/envs/r-reticulate/bin/python:1: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
ax = sns.heatmap(edges_series, 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = False, 
                 cbar = False)
ax.axis('off')
> (0.0, 1200.0, 19900.0, 0.0)
plt.show()

#Phase difference

import sys
sys.path.insert(1, 'libs/')

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from mpl_toolkits.mplot3d import Axes3D

theta = np.linspace(0*np.pi, 8*np.pi, 100)
time = np.linspace(0, 8, 100)
y1 = np.sin(theta)
x1 = np.cos(theta)
y2 = np.sin(theta + np.pi/2)
x2 = np.cos(theta + np.pi/2)
r = time/np.max(time)
ones = np.ones(time.shape[0])

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
plt.style.use('classic')

ax.plot(time, x1, y1, color = '#67001f', linewidth=2)
> [<mpl_toolkits.mplot3d.art3d.Line3D object at 0x7fc382a3dda0>]
ax.plot(time,ones,y1, linestyle = '--', color = '#0f0f0f')
> [<mpl_toolkits.mplot3d.art3d.Line3D object at 0x7fc382a96da0>]
ax.plot(time,x1,-ones, linestyle = '--', color = '#0f0f0f')
> [<mpl_toolkits.mplot3d.art3d.Line3D object at 0x7fc2f0b17320>]
ax.quiver(time,0,0,0, 0.99*x1, 0.99*y1, 
          length = 0.9, 
          normalize = False, 
          arrow_length_ratio = 0.1, 
          alpha = 0.4, 
          color = '#053061')
> <mpl_toolkits.mplot3d.art3d.Line3DCollection object at 0x7fc2f0b17160>
ax.text(0.5, 1, 0.5, r'$\sin(\theta)$', fontsize = 20)
> Text(0.5, 1, '$\\sin(\\theta)$')
ax.text(0.5, -1, -1, r'$\cos(\theta)$', fontsize = 20)
> Text(0.5, -1, '$\\cos(\\theta)$')
ax.set_xlabel('Time')
> Text(0.5, 0, 'Time')
ax.set_ylabel('Re')
> Text(0.5, 0, 'Re')
ax.set_zlabel('Im')
> Text(0.5, 0, 'Im')
ax.set_xlim(0,8)
> (0.0, 8.0)
ax.set_ylim(-1,1)
> (-1.0, 1.0)
ax.set_zlim(-1,1)
> (-1.0, 1.0)
plt.show()

colors1 = plt.cm.Reds(np.arange(0,1,0.01))
colors1[:,-1] = np.arange(0,1,0.01)

colors2 = plt.cm.Blues(np.arange(0,1,0.01))
colors2[:,-1] = np.arange(0,1,0.01)

fig = plt.figure(figsize = (12,8))
ax = fig.add_subplot(projection='3d')
plt.style.use('classic')

ax.scatter(time,ones,r*y1, color = colors1, marker = ",", s = 3)
> <mpl_toolkits.mplot3d.art3d.Path3DCollection object at 0x7fc2eef43cc0>
ax.scatter(time,r*x1,-ones, color = colors1, marker = ",", s = 3)
> <mpl_toolkits.mplot3d.art3d.Path3DCollection object at 0x7fc2f0b17cf8>
ax.scatter(time,ones,r*y2, color = colors2, marker = ",", s = 3)
> <mpl_toolkits.mplot3d.art3d.Path3DCollection object at 0x7fc28163bda0>
ax.scatter(time,r*x2,-ones, color = colors2, marker = ",", s = 3)
#ax.plot(time,r*x2,-ones, linestyle = '--', color = colors2[-10,:])
> <mpl_toolkits.mplot3d.art3d.Path3DCollection object at 0x7fc390b0acc0>
ax.quiver(time,0,0,0, 0.99*r*x1, 0.99*r*y1, 
          length = 0.9, 
          normalize = False, 
          arrow_length_ratio = 0.1, 
          alpha = 1, 
          color = colors1)
> <mpl_toolkits.mplot3d.art3d.Line3DCollection object at 0x7fc389b00c18>
ax.quiver(time,0,0,0, 0.99*r*x2, 0.99*r*y2, 
          length = 0.9, 
          normalize = False, 
          arrow_length_ratio = 0.1, 
          alpha = 1, 
          color = colors2)
> <mpl_toolkits.mplot3d.art3d.Line3DCollection object at 0x7fc389b00278>
ax.text(0.5, 1, 0.4, r'$A(t)$ $\sin(\theta)$', fontsize = 20)
> Text(0.5, 1, '$A(t)$ $\\sin(\\theta)$')
ax.text(0.5, -0.9, -1, r'$A(t)$ $\cos(\theta)$', fontsize = 20)
> Text(0.5, -0.9, '$A(t)$ $\\cos(\\theta)$')
ax.set_xlabel('Time')
> Text(0.5, 0, 'Time')
ax.set_ylabel('Re')
> Text(0.5, 0, 'Re')
ax.set_zlabel('Im')
> Text(0.5, 0, 'Im')
ax.set_xlim(0,8)
> (0.0, 8.0)
ax.set_ylim(-1,1)
> (-1.0, 1.0)
ax.set_zlim(-1,1)
> (-1.0, 1.0)
plt.show()

x1_vec = x1
x1_vec = x1_vec[99]
y1_vec = y1
y1_vec = y1_vec[99]

x2_vec = x2
x2_vec = x2_vec[99]
y2_vec = y2
y2_vec = y2_vec[99]

x, y = 0.0, 0.0

fig,ax = plt.subplots(1)
fig.set_figheight(6)
fig.set_figwidth(7)
ax.scatter(r*x1,r*y1, color = colors1, marker = ".", s = 100)
> <matplotlib.collections.PathCollection object at 0x7fc382a082b0>
ax.scatter(r*x2,r*y2, color = colors2, marker = ".", s = 100)
> <matplotlib.collections.PathCollection object at 0x7fc391336080>
ax.arrow(0,0,x1_vec,y1_vec, width = 0.015, color = colors1[-1,:], head_width = 0.1)
> <matplotlib.patches.FancyArrow object at 0x7fc390b2a390>
ax.arrow(0,0,x2_vec,y2_vec, width = 0.015, color = colors2[-1,:], head_width = 0.1)
> <matplotlib.patches.FancyArrow object at 0x7fc382a55390>
ax.add_patch(patches.Arc((x,y), 2.3, 2.3, theta1=0.0, theta2=90.0, linestyle = '--'))
> <matplotlib.patches.Arc object at 0x7fc382a55dd8>
ax.text(0.7,1, r'$\mathcal{\Delta\varphi = \frac{\pi}{2}}$', fontsize = 24)
> Text(0.7, 1, '$\\mathcal{\\Delta\\varphi = \\frac{\\pi}{2}}$')
ax.text(1.18*x1_vec,y1_vec, r'$\mathcal{\varphi}_{1}$', fontsize = 20)
> Text(1.18, -9.797174393178826e-16, '$\\mathcal{\\varphi}_{1}$')
ax.text(x2_vec,1.22*y2_vec, r'$\mathcal{\varphi}_{2}$', fontsize = 20)
> Text(-7.354070601250002e-16, 1.22, '$\\mathcal{\\varphi}_{2}$')
ax.set_xlim(-1.35,1.35)
> (-1.35, 1.35)
ax.set_ylim(-1.35,1.35)
> (-1.35, 1.35)
ax.set_xlabel('Re')
> Text(0.5, 0, 'Re')
ax.set_ylabel('Im')
> Text(0, 0.5, 'Im')
plt.show()

import sys
sys.path.insert(1, 'libs/')

import numpy as np
import scipy as sc
from scipy import io
import dynfc as dyn
import seaborn as sns
import matplotlib.pyplot as plt

ts = sc.io.loadmat('data/ts.mat')['ts']
ts = ts

RSsig = np.zeros((ts.shape[0],ts.shape[1],1))
RSsig[:,:,0] = ts

Phases, syncConn, leidaArray = dyn.run_multiPat(RSsig)
> Signal filtered.
> Phases obtained.
> Matrices obtained.
> Routine finished for patient no. 1.
mat1 = syncConn[:,:,0,0]

aa = plt.figure(figsize = [7,6])
ax = sns.heatmap(mat1, 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = True, 
                 cbar = True)
ax.axis('off')
> (0.0, 200.0, 200.0, 0.0)
ax.tick_params(left=False, bottom=False)
plt.show()

aa = plt.figure(figsize = (12/50,4))
ax = sns.heatmap(leidaArray[:,0,]/max(abs(leidaArray[:,0,])), 
                 cmap = "RdBu_r", 
                 vmin = -1, 
                 vmax = 1, 
                 square = False, 
                 cbar = False)
ax.axis('off')
> (0.0, 1.0, 1180.0, 0.0)
plt.show()

This document was prepared on 2021-02-14.

Package References

report::cite_packages(sessionInfo())
  • JJ Allaire and Yihui Xie and Jonathan McPherson and Javier Luraschi and Kevin Ushey and Aron Atkins and Hadley Wickham and Joe Cheng and Winston Chang and Richard Iannone (2020). rmarkdown: Dynamic Documents for R. R package version 2.6. URL https://rmarkdown.rstudio.com.
  • Kevin Ushey, JJ Allaire and Yuan Tang (2021). reticulate: Interface to ‘Python’. R package version 1.18-9007. https://github.com/rstudio/reticulate
  • R Core Team (2020). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. URL https://www.R-project.org/.
LS0tCnRpdGxlOiAnKipSZXN1bHRzIFRlbXBsYXRlKionCnN1YnRpdGxlOiBBIFN1YnRpdGxlCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGNlcnVsZWFuCiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgZGZfcHJpbnQ6IGthYmxlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICByZWZlcmVuY2VfZG9jeDogdXRpbHMvVGVtcGxhdGVfV29yZC5kb2N4CiAgICBoaWdobGlnaHQ6IHB5Z21lbnRzCiAgICB0b2M6IG5vCiAgICB0b2NfZGVwdGg6IDMKICAgIGRmX3ByaW50OiBrYWJsZQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICBybWFya2Rvd246Omh0bWxfdmlnbmV0dGU6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogJzInCiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQpiaWJsaW9ncmFwaHk6IHV0aWxzL2JpYmxpb2dyYXBoeS5iaWIKY3NsOiB1dGlscy9hcGEuY3NsCi0tLQoKCjwhLS0gCiEhISEgSU1QT1JUQU5UOiBydW4gYHNvdXJjZSgidXRpbHMvcmVuZGVyLlIiKWAgdG8gcHVibGlzaCBpbnN0ZWFkIG9mIGNsaWNraW5nIG9uICdLbml0JwotLT4KCiMjIFBhY2thZ2VzCgoKCmBgYHtyIHNldHVwLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPVRSVUUsIGluY2x1ZGU9RkFMU0V9CnNvdXJjZSgidXRpbHMvY29uZmlnLlIiKSAgCgpmYXN0IDwtIEZBTFNFICAjIE1ha2UgdGhpcyBmYWxzZSB0byBza2lwIHRoZSBjaHVua3MKYGBgCgoKCiMgSW50cm9kdWN0aW9uCgpgYGB7ciBiYWRnZXMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9VFJVRSwgd2FybmluZz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9CiMgVGhpcyBjaHVuayBpcyBhIGJpdCBjb21wbGV4IHNvIGRvbid0IHdvcnJ5IGFib3V0IGl0OiBpdCdzIG1hZGUgdG8gYWRkIGJhZGdlcyB0byB0aGUgSFRNTCB2ZXJzaW9ucwojIE5PVEU6IFlvdSBoYXZlIHRvIHJlcGxhY2UgdGhlIGxpbmtzIGFjY29yZGluZ2x5IHRvIGhhdmUgd29ya2luZyAiYnV0dG9ucyIgb24gdGhlIEhUTUwgdmVyc2lvbnMKaWYgKCFrbml0cjo6aXNfbGF0ZXhfb3V0cHV0KCkgJiYga25pdHI6OmlzX2h0bWxfb3V0cHV0KCkpIHsKICBjYXQoIiFbQnVpbGRdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFsaXR5QmVuZGluZy9UZW1wbGF0ZVJlc3VsdHMvd29ya2Zsb3dzL0J1aWxkL2JhZGdlLnN2ZykKICAgICAgWyFbV2Vic2l0ZV0oaHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS9yZXBvLVJlYWRtZS0yMTk2RjMpXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzKQogICAgICBbIVtXZWJzaXRlXShodHRwczovL2ltZy5zaGllbGRzLmlvL2JhZGdlL3Zpc2l0LXdlYnNpdGUtRTkxRTYzKV0oaHR0cHM6Ly9yZWFsaXR5YmVuZGluZy5naXRodWIuaW8vVGVtcGxhdGVSZXN1bHRzLykKICAgICAgWyFbV2Vic2l0ZV0oaHR0cHM6Ly9pbWcuc2hpZWxkcy5pby9iYWRnZS9kb3dubG9hZC0uZG9jeC1GRjU3MjIpXShodHRwczovL2dpdGh1Yi5jb20vUmVhbGl0eUJlbmRpbmcvVGVtcGxhdGVSZXN1bHRzL3Jhdy9tYWluL3dvcmRfYW5kX3BkZi9TdXBwbGVtZW50YXJ5TWF0ZXJpYWxzLmRvY3gpCiAgICAgIFshW1dlYnNpdGVdKGh0dHBzOi8vaW1nLnNoaWVsZHMuaW8vYmFkZ2Uvc2VlLS5wZGYtRkY5ODAwKV0oaHR0cHM6Ly9naXRodWIuY29tL1JlYWxpdHlCZW5kaW5nL1RlbXBsYXRlUmVzdWx0cy9ibG9iL21haW4vd29yZF9hbmRfcGRmL1N1cHBsZW1lbnRhcnlNYXRlcmlhbHMucGRmKSIpCn0KYGBgCgoKIyBTbGlkaW5nIHdpbmRvd3MKCmBgYHtweXRob259CmltcG9ydCBzeXMKc3lzLnBhdGguaW5zZXJ0KDEsICdsaWJzLycpCgppbXBvcnQgZHluZmMgYXMgZHluCmltcG9ydCBudW1weSBhcyBucApmcm9tIG51bXB5LnJhbmRvbSBpbXBvcnQgc2VlZCwgcmFuZAppbXBvcnQgc2NpcHkgYXMgc2MKZnJvbSBzY2lweSBpbXBvcnQgaW8KaW1wb3J0IHNlYWJvcm4gYXMgc25zCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKaW1wb3J0IG1hdHBsb3RsaWIuY2Jvb2sgYXMgY2Jvb2sKaW1wb3J0IG1hdHBsb3RsaWIuY20gYXMgY20KaW1wb3J0IG1hdHBsb3RsaWIucGF0Y2hlcyBhcyBwYXRjaGVzCgpmb250ID0geyd3ZWlnaHQnIDogJ3JlZ3VsYXInLAogICAgICAgICdzaXplJyAgIDogMjR9CnBsdC5yYygnZm9udCcsICoqZm9udCkKCnRzID0gc2MuaW8ubG9hZG1hdCgnZGF0YS90cy5tYXQnKVsndHMnXQp0cyA9IHRzLnRyYW5zcG9zZSgpCgpjb3JyX21hdHMsIGlkeCA9IGR5bi5jb3JyX3NsaWRlKHRzLDMwMCw1MCkKCmlkeC5zaGFwZQoKYSA9IFsxLDEsMSwxLDEuNl0KCmZpZyxheCA9IHBsdC5zdWJwbG90cygxKQpmaWcuc2V0X2ZpZ2hlaWdodCgxMCkKZmlnLnNldF9maWd3aWR0aCgyMCkKcGx0LnN0eWxlLnVzZSgndGFibGVhdS1jb2xvcmJsaW5kMTAnKQpmb3IgaSBpbiByYW5nZSg1KToKICAgIAogICAgcGx0LnBsb3QoMippKmFbaV0gKyB0c1tpLF0vMS40KSAgIAogICAgCnBsdC54bGFiZWwoJ1RpbWUgW1RSc10nKQpwbHQueWxhYmVsKCdCT0xEJykKYXgudGlja19wYXJhbXMobGVmdD1GYWxzZSkKYXguc2V0X3l0aWNrbGFiZWxzKFtdKQpheC5zZXRfeWxpbSgtMywxNS40KQpheC5zZXRfeGxpbSgwLDEyMDApCnJlY3QgPSBwYXRjaGVzLlJlY3RhbmdsZSgoaWR4WzBdLC0yLjgpLDMwMCwxOCxsaW5ld2lkdGg9NCxlZGdlY29sb3I9JyM1OTU5NTknLGZhY2Vjb2xvcj0nbm9uZScpCmF4LmFkZF9wYXRjaChyZWN0KQpyZWN0ID0gcGF0Y2hlcy5SZWN0YW5nbGUoKGlkeFs1XSwtMi44KSwzMDAsMTgsbGluZXdpZHRoPTQsZWRnZWNvbG9yPScjQTU2QjZCJyxmYWNlY29sb3I9J25vbmUnKQpheC5hZGRfcGF0Y2gocmVjdCkKcmVjdCA9IHBhdGNoZXMuUmVjdGFuZ2xlKChpZHhbOV0sLTIuOCksMzAwLDE4LGxpbmV3aWR0aD00LGVkZ2Vjb2xvcj0nI0NFM0UzRScsZmFjZWNvbG9yPSdub25lJykKYXguYWRkX3BhdGNoKHJlY3QpCnJlY3QgPSBwYXRjaGVzLlJlY3RhbmdsZSgoaWR4WzE2XSwtMi44KSwzMDAsMTgsbGluZXdpZHRoPTQsZWRnZWNvbG9yPScjRkYwMDAwJyxmYWNlY29sb3I9J25vbmUnKQpheC5hZGRfcGF0Y2gocmVjdCkKcGx0LnNob3coKQpgYGAKCmBgYHtweXRob259CmltcG9ydCBzeXMKc3lzLnBhdGguaW5zZXJ0KDEsICdsaWJzLycpCgppbXBvcnQgZHluZmMgYXMgZHluCmltcG9ydCBudW1weSBhcyBucApmcm9tIG51bXB5LnJhbmRvbSBpbXBvcnQgc2VlZCwgcmFuZAppbXBvcnQgc2NpcHkgYXMgc2MKZnJvbSBzY2lweSBpbXBvcnQgaW8KaW1wb3J0IHNlYWJvcm4gYXMgc25zCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKaW1wb3J0IG1hdHBsb3RsaWIuY2Jvb2sgYXMgY2Jvb2sKaW1wb3J0IG1hdHBsb3RsaWIuY20gYXMgY20KaW1wb3J0IG1hdHBsb3RsaWIucGF0Y2hlcyBhcyBwYXRjaGVzCgphYSA9IHBsdC5maWd1cmUoZmlnc2l6ZSA9IFs2LDZdKQpheCA9IHNucy5oZWF0bWFwKGNvcnJfbWF0c1s6LDosMF0sIAogICAgICAgICAgICAgICAgIGNtYXAgPSAiUmRCdV9yIiwgCiAgICAgICAgICAgICAgICAgdm1pbiA9IC0xLCAKICAgICAgICAgICAgICAgICB2bWF4ID0gMSwgCiAgICAgICAgICAgICAgICAgc3F1YXJlID0gVHJ1ZSwgCiAgICAgICAgICAgICAgICAgY2JhciA9IEZhbHNlKQpheC5heGlzKCdvZmYnKQpheC50aWNrX3BhcmFtcyhsZWZ0PUZhbHNlLCBib3R0b209RmFsc2UpCiAgICAKcGx0LnNob3coKQoKYWEgPSBwbHQuZmlndXJlKGZpZ3NpemUgPSBbNiw2XSkKYXggPSBzbnMuaGVhdG1hcChjb3JyX21hdHNbOiw6LDVdLCAKICAgICAgICAgICAgICAgICBjbWFwID0gIlJkQnVfciIsIAogICAgICAgICAgICAgICAgIHZtaW4gPSAtMSwgCiAgICAgICAgICAgICAgICAgdm1heCA9IDEsIAogICAgICAgICAgICAgICAgIHNxdWFyZSA9IFRydWUsIAogICAgICAgICAgICAgICAgIGNiYXIgPSBGYWxzZSkKYXguYXhpcygnb2ZmJykKYXgudGlja19wYXJhbXMobGVmdD1GYWxzZSwgYm90dG9tPUZhbHNlKQogICAgCnBsdC5zaG93KCkKCmFhID0gcGx0LmZpZ3VyZShmaWdzaXplID0gWzYsNl0pCmF4ID0gc25zLmhlYXRtYXAoY29ycl9tYXRzWzosOiw5XSwgCiAgICAgICAgICAgICAgICAgY21hcCA9ICJSZEJ1X3IiLCAKICAgICAgICAgICAgICAgICB2bWluID0gLTEsIAogICAgICAgICAgICAgICAgIHZtYXggPSAxLCAKICAgICAgICAgICAgICAgICBzcXVhcmUgPSBUcnVlLCAKICAgICAgICAgICAgICAgICBjYmFyID0gRmFsc2UpCmF4LmF4aXMoJ29mZicpCmF4LnRpY2tfcGFyYW1zKGxlZnQ9RmFsc2UsIGJvdHRvbT1GYWxzZSkKICAgIApwbHQuc2hvdygpCgphYSA9IHBsdC5maWd1cmUoZmlnc2l6ZSA9IFs2LDZdKQpheCA9IHNucy5oZWF0bWFwKGNvcnJfbWF0c1s6LDosMTZdLCAKICAgICAgICAgICAgICAgICBjbWFwID0gIlJkQnVfciIsIAogICAgICAgICAgICAgICAgIHZtaW4gPSAtMSwgCiAgICAgICAgICAgICAgICAgdm1heCA9IDEsIAogICAgICAgICAgICAgICAgIHNxdWFyZSA9IFRydWUsIAogICAgICAgICAgICAgICAgIGNiYXIgPSBGYWxzZSkKYXguYXhpcygnb2ZmJykKYXgudGlja19wYXJhbXMobGVmdD1GYWxzZSwgYm90dG9tPUZhbHNlKQogICAgCnBsdC5zaG93KCkKCmBgYAoKIyBDb2ZsdWN0dWF0aW9ucwoKYGBge3B5dGhvbn0KaW1wb3J0IHN5cwpzeXMucGF0aC5pbnNlcnQoMSwgJ2xpYnMvJykKCmltcG9ydCBudW1weSBhcyBucAppbXBvcnQgc2NpcHkgYXMgc2MKZnJvbSBzY2lweSBpbXBvcnQgaW8KaW1wb3J0IGR5bmZjIGFzIGR5bgppbXBvcnQgc2VhYm9ybiBhcyBzbnMKaW1wb3J0IG1hdHBsb3RsaWIucHlwbG90IGFzIHBsdAoKdHMgPSBzYy5pby5sb2FkbWF0KCdkYXRhL3RzLm1hdCcpWyd0cyddCnRzID0gdHMudHJhbnNwb3NlKCkKCm1hdDEsIHJzcyA9IGR5bi5jb3JyX3NsaWRlKHRzLDI0KQptYXQxID0gbWF0MVs6LDosMF0KCmFhID0gcGx0LmZpZ3VyZShmaWdzaXplID0gWzYsNl0pCmF4ID0gc25zLmhlYXRtYXAobWF0MSwgCiAgICAgICAgICAgICAgICAgY21hcCA9ICJSZEJ1X3IiLCAKICAgICAgICAgICAgICAgICB2bWluID0gLTEsIAogICAgICAgICAgICAgICAgIHZtYXggPSAxLCAKICAgICAgICAgICAgICAgICBzcXVhcmUgPSBGYWxzZSwgCiAgICAgICAgICAgICAgICAgY2JhciA9IFRydWUpCmF4LmF4aXMoJ29mZicpCmF4LnRpY2tfcGFyYW1zKGxlZnQ9RmFsc2UsIGJvdHRvbT1GYWxzZSkKcGx0LnNob3coKQoKdXB0ID0gbnAudHJpdV9pbmRpY2VzKG1hdDEuc2hhcGVbMF0sIGsgPSAxKQp2ZWMgPSAobWF0MVt1cHRdKQoKdG9QbG90ID0gbnAuemVyb3MoKHZlYy5zaGFwZVswXSwxKSkKdG9QbG90WzosMF0gPSB2ZWMKCmFhID0gcGx0LmZpZ3VyZShmaWdzaXplID0gKDEyLzUwLDQpKQpheCA9IHNucy5oZWF0bWFwKHRvUGxvdFs6LDA6MV0sIAogICAgICAgICAgICAgICAgIGNtYXAgPSAiUmRCdV9yIiwgCiAgICAgICAgICAgICAgICAgdm1pbiA9IC0xLCAKICAgICAgICAgICAgICAgICB2bWF4ID0gMSwgCiAgICAgICAgICAgICAgICAgc3F1YXJlID0gRmFsc2UsIAogICAgICAgICAgICAgICAgIGNiYXIgPSBGYWxzZSkKYXguYXhpcygnb2ZmJykKcGx0LnNob3coKQoKZWRnZXNfc2VyaWVzLCBjb3JyX21hdHMsIHJzcyA9IGR5bi5jb2ZsdWN0KHRzLCAyNCkKCmFhID0gcGx0LmZpZ3VyZShmaWdzaXplID0gKDEyLDQpKQpheCA9IHNucy5oZWF0bWFwKGVkZ2VzX3NlcmllcywgCiAgICAgICAgICAgICAgICAgY21hcCA9ICJSZEJ1X3IiLCAKICAgICAgICAgICAgICAgICB2bWluID0gLTEsIAogICAgICAgICAgICAgICAgIHZtYXggPSAxLCAKICAgICAgICAgICAgICAgICBzcXVhcmUgPSBGYWxzZSwgCiAgICAgICAgICAgICAgICAgY2JhciA9IEZhbHNlKQpheC5heGlzKCdvZmYnKQpwbHQuc2hvdygpCmBgYAoKI1BoYXNlIGRpZmZlcmVuY2UKCmBgYHtweXRob259CmltcG9ydCBzeXMKc3lzLnBhdGguaW5zZXJ0KDEsICdsaWJzLycpCgppbXBvcnQgbnVtcHkgYXMgbnAKaW1wb3J0IG1hdHBsb3RsaWIucHlwbG90IGFzIHBsdAppbXBvcnQgbWF0cGxvdGxpYi5wYXRjaGVzIGFzIHBhdGNoZXMKZnJvbSBtcGxfdG9vbGtpdHMubXBsb3QzZCBpbXBvcnQgQXhlczNECgp0aGV0YSA9IG5wLmxpbnNwYWNlKDAqbnAucGksIDgqbnAucGksIDEwMCkKdGltZSA9IG5wLmxpbnNwYWNlKDAsIDgsIDEwMCkKeTEgPSBucC5zaW4odGhldGEpCngxID0gbnAuY29zKHRoZXRhKQp5MiA9IG5wLnNpbih0aGV0YSArIG5wLnBpLzIpCngyID0gbnAuY29zKHRoZXRhICsgbnAucGkvMikKciA9IHRpbWUvbnAubWF4KHRpbWUpCm9uZXMgPSBucC5vbmVzKHRpbWUuc2hhcGVbMF0pCgpmaWcgPSBwbHQuZmlndXJlKCkKYXggPSBmaWcuYWRkX3N1YnBsb3QocHJvamVjdGlvbj0nM2QnKQpwbHQuc3R5bGUudXNlKCdjbGFzc2ljJykKCmF4LnBsb3QodGltZSwgeDEsIHkxLCBjb2xvciA9ICcjNjcwMDFmJywgbGluZXdpZHRoPTIpCmF4LnBsb3QodGltZSxvbmVzLHkxLCBsaW5lc3R5bGUgPSAnLS0nLCBjb2xvciA9ICcjMGYwZjBmJykKYXgucGxvdCh0aW1lLHgxLC1vbmVzLCBsaW5lc3R5bGUgPSAnLS0nLCBjb2xvciA9ICcjMGYwZjBmJykKYXgucXVpdmVyKHRpbWUsMCwwLDAsIDAuOTkqeDEsIDAuOTkqeTEsIAogICAgICAgICAgbGVuZ3RoID0gMC45LCAKICAgICAgICAgIG5vcm1hbGl6ZSA9IEZhbHNlLCAKICAgICAgICAgIGFycm93X2xlbmd0aF9yYXRpbyA9IDAuMSwgCiAgICAgICAgICBhbHBoYSA9IDAuNCwgCiAgICAgICAgICBjb2xvciA9ICcjMDUzMDYxJykKYXgudGV4dCgwLjUsIDEsIDAuNSwgcickXHNpbihcdGhldGEpJCcsIGZvbnRzaXplID0gMjApCmF4LnRleHQoMC41LCAtMSwgLTEsIHInJFxjb3MoXHRoZXRhKSQnLCBmb250c2l6ZSA9IDIwKQpheC5zZXRfeGxhYmVsKCdUaW1lJykKYXguc2V0X3lsYWJlbCgnUmUnKQpheC5zZXRfemxhYmVsKCdJbScpCmF4LnNldF94bGltKDAsOCkKYXguc2V0X3lsaW0oLTEsMSkKYXguc2V0X3psaW0oLTEsMSkKcGx0LnNob3coKQoKY29sb3JzMSA9IHBsdC5jbS5SZWRzKG5wLmFyYW5nZSgwLDEsMC4wMSkpCmNvbG9yczFbOiwtMV0gPSBucC5hcmFuZ2UoMCwxLDAuMDEpCgpjb2xvcnMyID0gcGx0LmNtLkJsdWVzKG5wLmFyYW5nZSgwLDEsMC4wMSkpCmNvbG9yczJbOiwtMV0gPSBucC5hcmFuZ2UoMCwxLDAuMDEpCgpmaWcgPSBwbHQuZmlndXJlKGZpZ3NpemUgPSAoMTIsOCkpCmF4ID0gZmlnLmFkZF9zdWJwbG90KHByb2plY3Rpb249JzNkJykKcGx0LnN0eWxlLnVzZSgnY2xhc3NpYycpCgpheC5zY2F0dGVyKHRpbWUsb25lcyxyKnkxLCBjb2xvciA9IGNvbG9yczEsIG1hcmtlciA9ICIsIiwgcyA9IDMpCmF4LnNjYXR0ZXIodGltZSxyKngxLC1vbmVzLCBjb2xvciA9IGNvbG9yczEsIG1hcmtlciA9ICIsIiwgcyA9IDMpCmF4LnNjYXR0ZXIodGltZSxvbmVzLHIqeTIsIGNvbG9yID0gY29sb3JzMiwgbWFya2VyID0gIiwiLCBzID0gMykKYXguc2NhdHRlcih0aW1lLHIqeDIsLW9uZXMsIGNvbG9yID0gY29sb3JzMiwgbWFya2VyID0gIiwiLCBzID0gMykKI2F4LnBsb3QodGltZSxyKngyLC1vbmVzLCBsaW5lc3R5bGUgPSAnLS0nLCBjb2xvciA9IGNvbG9yczJbLTEwLDpdKQpheC5xdWl2ZXIodGltZSwwLDAsMCwgMC45OSpyKngxLCAwLjk5KnIqeTEsIAogICAgICAgICAgbGVuZ3RoID0gMC45LCAKICAgICAgICAgIG5vcm1hbGl6ZSA9IEZhbHNlLCAKICAgICAgICAgIGFycm93X2xlbmd0aF9yYXRpbyA9IDAuMSwgCiAgICAgICAgICBhbHBoYSA9IDEsIAogICAgICAgICAgY29sb3IgPSBjb2xvcnMxKQpheC5xdWl2ZXIodGltZSwwLDAsMCwgMC45OSpyKngyLCAwLjk5KnIqeTIsIAogICAgICAgICAgbGVuZ3RoID0gMC45LCAKICAgICAgICAgIG5vcm1hbGl6ZSA9IEZhbHNlLCAKICAgICAgICAgIGFycm93X2xlbmd0aF9yYXRpbyA9IDAuMSwgCiAgICAgICAgICBhbHBoYSA9IDEsIAogICAgICAgICAgY29sb3IgPSBjb2xvcnMyKQpheC50ZXh0KDAuNSwgMSwgMC40LCByJyRBKHQpJCAkXHNpbihcdGhldGEpJCcsIGZvbnRzaXplID0gMjApCmF4LnRleHQoMC41LCAtMC45LCAtMSwgcickQSh0KSQgJFxjb3MoXHRoZXRhKSQnLCBmb250c2l6ZSA9IDIwKQpheC5zZXRfeGxhYmVsKCdUaW1lJykKYXguc2V0X3lsYWJlbCgnUmUnKQpheC5zZXRfemxhYmVsKCdJbScpCmF4LnNldF94bGltKDAsOCkKYXguc2V0X3lsaW0oLTEsMSkKYXguc2V0X3psaW0oLTEsMSkKcGx0LnNob3coKQoKeDFfdmVjID0geDEKeDFfdmVjID0geDFfdmVjWzk5XQp5MV92ZWMgPSB5MQp5MV92ZWMgPSB5MV92ZWNbOTldCgp4Ml92ZWMgPSB4Mgp4Ml92ZWMgPSB4Ml92ZWNbOTldCnkyX3ZlYyA9IHkyCnkyX3ZlYyA9IHkyX3ZlY1s5OV0KCngsIHkgPSAwLjAsIDAuMAoKZmlnLGF4ID0gcGx0LnN1YnBsb3RzKDEpCmZpZy5zZXRfZmlnaGVpZ2h0KDYpCmZpZy5zZXRfZmlnd2lkdGgoNykKYXguc2NhdHRlcihyKngxLHIqeTEsIGNvbG9yID0gY29sb3JzMSwgbWFya2VyID0gIi4iLCBzID0gMTAwKQpheC5zY2F0dGVyKHIqeDIscip5MiwgY29sb3IgPSBjb2xvcnMyLCBtYXJrZXIgPSAiLiIsIHMgPSAxMDApCmF4LmFycm93KDAsMCx4MV92ZWMseTFfdmVjLCB3aWR0aCA9IDAuMDE1LCBjb2xvciA9IGNvbG9yczFbLTEsOl0sIGhlYWRfd2lkdGggPSAwLjEpCmF4LmFycm93KDAsMCx4Ml92ZWMseTJfdmVjLCB3aWR0aCA9IDAuMDE1LCBjb2xvciA9IGNvbG9yczJbLTEsOl0sIGhlYWRfd2lkdGggPSAwLjEpCmF4LmFkZF9wYXRjaChwYXRjaGVzLkFyYygoeCx5KSwgMi4zLCAyLjMsIHRoZXRhMT0wLjAsIHRoZXRhMj05MC4wLCBsaW5lc3R5bGUgPSAnLS0nKSkKYXgudGV4dCgwLjcsMSwgcickXG1hdGhjYWx7XERlbHRhXHZhcnBoaSA9IFxmcmFje1xwaX17Mn19JCcsIGZvbnRzaXplID0gMjQpCmF4LnRleHQoMS4xOCp4MV92ZWMseTFfdmVjLCByJyRcbWF0aGNhbHtcdmFycGhpfV97MX0kJywgZm9udHNpemUgPSAyMCkKYXgudGV4dCh4Ml92ZWMsMS4yMip5Ml92ZWMsIHInJFxtYXRoY2Fse1x2YXJwaGl9X3syfSQnLCBmb250c2l6ZSA9IDIwKQpheC5zZXRfeGxpbSgtMS4zNSwxLjM1KQpheC5zZXRfeWxpbSgtMS4zNSwxLjM1KQpheC5zZXRfeGxhYmVsKCdSZScpCmF4LnNldF95bGFiZWwoJ0ltJykKcGx0LnNob3coKQpgYGAKCmBgYHtweXRob259CmltcG9ydCBzeXMKc3lzLnBhdGguaW5zZXJ0KDEsICdsaWJzLycpCgppbXBvcnQgbnVtcHkgYXMgbnAKaW1wb3J0IHNjaXB5IGFzIHNjCmZyb20gc2NpcHkgaW1wb3J0IGlvCmltcG9ydCBkeW5mYyBhcyBkeW4KaW1wb3J0IHNlYWJvcm4gYXMgc25zCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKCnRzID0gc2MuaW8ubG9hZG1hdCgnZGF0YS90cy5tYXQnKVsndHMnXQp0cyA9IHRzCgpSU3NpZyA9IG5wLnplcm9zKCh0cy5zaGFwZVswXSx0cy5zaGFwZVsxXSwxKSkKUlNzaWdbOiw6LDBdID0gdHMKClBoYXNlcywgc3luY0Nvbm4sIGxlaWRhQXJyYXkgPSBkeW4ucnVuX211bHRpUGF0KFJTc2lnKQoKbWF0MSA9IHN5bmNDb25uWzosOiwwLDBdCgphYSA9IHBsdC5maWd1cmUoZmlnc2l6ZSA9IFs3LDZdKQpheCA9IHNucy5oZWF0bWFwKG1hdDEsIAogICAgICAgICAgICAgICAgIGNtYXAgPSAiUmRCdV9yIiwgCiAgICAgICAgICAgICAgICAgdm1pbiA9IC0xLCAKICAgICAgICAgICAgICAgICB2bWF4ID0gMSwgCiAgICAgICAgICAgICAgICAgc3F1YXJlID0gVHJ1ZSwgCiAgICAgICAgICAgICAgICAgY2JhciA9IFRydWUpCmF4LmF4aXMoJ29mZicpCmF4LnRpY2tfcGFyYW1zKGxlZnQ9RmFsc2UsIGJvdHRvbT1GYWxzZSkKcGx0LnNob3coKQoKYWEgPSBwbHQuZmlndXJlKGZpZ3NpemUgPSAoMTIvNTAsNCkpCmF4ID0gc25zLmhlYXRtYXAobGVpZGFBcnJheVs6LDAsXS9tYXgoYWJzKGxlaWRhQXJyYXlbOiwwLF0pKSwgCiAgICAgICAgICAgICAgICAgY21hcCA9ICJSZEJ1X3IiLCAKICAgICAgICAgICAgICAgICB2bWluID0gLTEsIAogICAgICAgICAgICAgICAgIHZtYXggPSAxLCAKICAgICAgICAgICAgICAgICBzcXVhcmUgPSBGYWxzZSwgCiAgICAgICAgICAgICAgICAgY2JhciA9IEZhbHNlKQpheC5heGlzKCdvZmYnKQpwbHQuc2hvdygpCmBgYAoKClRoaXMgZG9jdW1lbnQgd2FzIHByZXBhcmVkIG9uIGByIGZvcm1hdChTeXMuRGF0ZSgpKWAuIAoKCiMgUGFja2FnZSBSZWZlcmVuY2VzCgpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KcmVwb3J0OjpjaXRlX3BhY2thZ2VzKHNlc3Npb25JbmZvKCkpCmBgYAoK